var express = require('express')
  , _       = require('underscore')
  , routes  = require('./routes')
  , user    = require('./routes/user')
  , api     = require('./routes/api')
  , page    = require('./routes/page')
  , location= require('./routes/location')
  , conversation= require('./routes/conversation')
  , note= require('./routes/note')
  , path    = require('path')
  , http    = require('http')
  , fs      = require('fs')
  , db      = require('./models')
  , redisC  = require('redis')
  , redis   = redisC.createClient()
  , cors    = require('cors')
  , config = require('./config/config.json');

var passport = require('passport'),
    LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy({ usernameField: 'email' },
    function(email, password, done) {
        return user.findByUsername(passport, email, password, done);
    }
));

var forgot = require('./routes/password_reset_request')({
    uri: 'http://localhost:3000/password_reset',
    from: 'password-robot@localhost',
    transportType: 'SMTP',
    transportOptions: {
        service: "Gmail",
        auth: {
            user: config.credentials.email,
            pass: config.credentials.password
        }
    }
});

var confirm = require('./routes/confirmation')({
  uri: 'http://localhost:3000/confirm_register',
  from: 'password-robot@localhost',
  transportType: 'SMTP',
  transportOptions: {
    service: "Gmail",
    auth: {
      user: config.credentials.email,
      pass: config.credentials.password
    }
  }
});

//app
var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());

// TODO:
// according to this: http://stackoverflow.com/questions/5710358/how-to-get-post-query-in-express-node-js
// the use of bodyParser is not recommended, as it is equivalent to use of json and urlencoded middleware, in addition 
// to an unsafe multipart - we should review and remove this before release
// also here: http://andrewkelley.me/post/do-not-use-bodyparser-with-express-js.html
app.use(express.bodyParser());

app.use(express.cookieParser('your secret here'));
app.use(express.session());

//app.use(express.cookieParser());
//app.use(express.session({secret: 'blahblah', cookie: { maxAge: 10000 }}));


app.use(passport.initialize());
app.use(passport.session());

app.use(express.static(path.join(__dirname, 'public')));
app.use(app.router);

// app.use(require('sesame')()); // for password reset sessions, not sure if necessary

app.configure('development', function(){
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
    app.use(express.errorHandler());
});

// route to test if the user is logged in or not
app.get('/loggedin', function(req, res) {
  res.send(req.isAuthenticated() ? req.user : '0');
});

app.get('/page/:id', apiAuthenticated, page.show);

//gets and posts
app.get('/', webAuthenticated, routes.home);

app.get('/login', user.loginPage);
app.get('/login_frame', user.loginFrame);
app.get('/register', user.registerPage);
app.get('/logout', user.logout);
app.get('/reset', user.resetPage);
app.get('/forgot', user.forgotPage);
app.get('/password_reset', user.resetMe);
app.get('/confirm_register', user.confirmMe);

app.post('/login', user.login(passport));
app.post('/Register', user.register(confirm));

// forgot password
app.post('/forgot', express.bodyParser(), user.forgot(forgot));
app.post('/reset', express.bodyParser(), user.reset(forgot));


// //////////////// TOKEN BASED EXTERNAL API ////////////////////
// route to test if the user is logged in or not
app.get('/api/loggedin', apiAuthenticated, cors(), function(req, res) {
  console.log("Loggedin indeed...");
  res.send(200);
});
app.post('/api/login',  user.api_login(passport));
app.get( '/api/login',  apiAuthenticated, user.api_tokens);

app.get( '/api/drawer', api.drawer); // public access api to get drawer 
app.get( '/api/state',  apiAuthenticated, cors(), api.state);
app.post('/api/act',    apiAuthenticated, cors(), api.act);

// REST API for locations, conversations, participants and notes
app.get( '/api/locations',      apiAuthenticated, cors(), location.list);
//app.get( '/api/locations',      webAuthenticated, cors(), location.list);
app.post('/api/locations',      apiAuthenticated, cors(), location.create);
app.get( '/api/location/:id',   apiAuthenticated, cors(), location.get);
app.options('/api/location/:id',apiAuthenticated, cors());
app.put( '/api/location/:id',   apiAuthenticated, cors(), location.update);
app.delete('/api/location/:id', apiAuthenticated, cors(), location.remove);

app.get( '/api/conversations', apiAuthenticated, cors(), conversation.list);
app.get( '/api/conversations/top', apiAuthenticated, cors(), conversation.top);
app.post('/api/conversations', apiAuthenticated, cors(), conversation.create);
app.get( '/api/conversation/:id', apiAuthenticated, cors(), conversation.get);
app.options('/api/conversation/:id',apiAuthenticated, cors());
app.put( '/api/conversation/:id', apiAuthenticated, cors(), conversation.update);
app.delete( '/api/conversation/:id', apiAuthenticated, cors(), conversation.remove);

app.get( '/api/notes', apiAuthenticated, cors(), note.list);
app.post('/api/notes', apiAuthenticated, cors(), note.create);
app.get( '/api/note/:id', apiAuthenticated, cors(), note.get);
app.options('/api/note/:id',apiAuthenticated, cors());
app.put( '/api/note/:id', apiAuthenticated, cors(), note.update);
app.delete( '/api/note/:id', apiAuthenticated, cors(), note.remove);



// Served .jade angular partials
app.get('/partials/:name', function (req, res)
 { var name = req.params.name;
   res.render('partials/' + name);
});

db
  .sequelize
  .sync()
  .complete(function(err) {
    if (err) {
      throw err
    } else {
      //start server
      http.createServer(app).listen(app.get('port'), function(){
        console.log('Bookies server listening on port ' + app.get('port'));
      });
    }
  })


// /////////////////////////////////////////////////////////////
// AUTH 

function webAuthenticated(req, res, next) {
  if (req.isAuthenticated()) { return next(); }
  res.redirect('/login');
}

function apiAuthenticated(req, res, next) {
  var user_guid    = req.query.user_guid;
  var access_token = req.query.access_token;

  if (user_guid && access_token) {

    console.log("=========== API AUTH ============");
    console.log("User id: ",  user_guid);
    console.log("Access token: ", access_token);

    redis.get('user_guid_' + user_guid, function(err, result) {
      console.log("Got creds from redis", result);
      var credentials = JSON.parse(result);
      if(credentials && credentials.access_token === access_token) {
        console.log("Token matches!");
        // TODO: Cache
        db.User.find(credentials.user_id).success(function(user) {
          if (user) {
            console.log("User found");
            req.user = user;
            return next();
          }
          res.send(401);
        });
      }
      else {
        res.send(401);
      } 
    });
  }
  else {
    if (req.isAuthenticated()) {
      return next();
    }
    res.send(401);
  }
}


